const { PointRule, PointTransaction } = require('../models');
const { Op } = require('sequelize');
const logger = require('../utils/logger');

class PointRuleService {
  /**
   * 创建积分规则
   * @param {Object} data - 积分规则数据
   * @returns {Promise<Object>} - 创建的积分规则
   */
  async createPointRule(data) {
    try {
      const pointRule = await PointRule.create(data);
      logger.info(`积分规则创建成功，ID: ${pointRule.id}`);
      return pointRule;
    } catch (error) {
      logger.error('创建积分规则时出错:', error);
      throw error;
    }
  }

  /**
   * 获取积分规则列表
   * @param {Object} filters - 过滤条件
   * @returns {Promise<Array<Object>>} - 积分规则列表
   */
  async getPointRules(filters = {}) {
    try {
      const where = {};
      if (filters.type) {
        where.type = filters.type;
      }
      if (filters.status) {
        where.status = filters.status;
      }
      if (filters.search) {
        where[Op.or] = [
          { name: { [Op.like]: `%${filters.search}%` } },
          { description: { [Op.like]: `%${filters.search}%` } }
        ];
      }

      // 添加有效期范围过滤
      if (filters.validFrom) {
        where.validFrom = { [Op.lte]: filters.validFrom };
      }
      if (filters.validTo) {
        where.validTo = { [Op.gte]: filters.validTo };
      }

      const pointRules = await PointRule.findAll({ where });
      return pointRules;
    } catch (error) {
      logger.error('获取积分规则列表时出错:', error);
      throw error;
    }
  }

  /**
   * 获取活动积分规则
   * @returns {Promise<Array<Object>>} - 活动积分规则列表
   */
  async getActiveRules() {
    try {
      const currentDate = new Date();
      const activeRules = await PointRule.findAll({
        where: {
          status: 'active',
          validFrom: { [Op.lte]: currentDate },
          validTo: { [Op.gte]: currentDate }
        }
      });
      return activeRules;
    } catch (error) {
      logger.error('获取活动积分规则时出错:', error);
      throw error;
    }
  }

  /**
   * 获取积分规则详情
   * @param {number} id - 积分规则ID
   * @returns {Promise<Object>} - 积分规则详情
   */
  async getPointRuleById(id) {
    try {
      const pointRule = await PointRule.findByPk(id);
      if (!pointRule) {
        throw new Error('Point rule not found');
      }
      return pointRule;
    } catch (error) {
      logger.error(`Error getting point rule with ID ${id}:`, error);
      throw error;
    }
  }

  /**
   * 更新积分规则
   * @param {number} id - 积分规则ID
   * @param {Object} data - 更新数据
   * @returns {Promise<Object>} - 更新后的积分规则
   */
  async updatePointRule(id, data) {
    try {
      const pointRule = await this.getPointRuleById(id);
      await pointRule.update(data);
      logger.info(`Point rule ${id} updated successfully`);
      return pointRule;
    } catch (error) {
      logger.error(`Error updating point rule ${id}:`, error);
      throw error;
    }
  }

  /**
   * 删除积分规则
   * @param {number} id - 积分规则ID
   * @returns {Promise<boolean>} - 删除结果
   */
  async deletePointRule(id) {
    try {
      const pointRule = await this.getPointRuleById(id);
      await pointRule.destroy();
      logger.info(`Point rule ${id} deleted successfully`);
      return true;
    } catch (error) {
      logger.error(`Error deleting point rule ${id}:`, error);
      throw error;
    }
  }

  /**
   * 更新积分规则状态
   * @param {number} id - 积分规则ID
   * @param {string} status - 状态
   * @returns {Promise<Object>} - 更新后的积分规则
   */
  async updatePointRuleStatus(id, status) {
    try {
      const pointRule = await this.getPointRuleById(id);
      await pointRule.update({ status });
      logger.info(`Point rule ${id} status updated to ${status}`);
      return pointRule;
    } catch (error) {
      logger.error(`Error updating point rule ${id} status:`, error);
      throw error;
    }
  }

  /**
   * 验证积分规则
   * @param {number} ruleId - 积分规则ID
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} - 验证结果
   */
  async validatePointRule(ruleId, userId) {
    try {
      const rule = await this.getPointRuleById(ruleId);
      const currentDate = new Date();

      // 检查规则是否有效且在有效期内
      if (rule.status !== 'active' ||
          currentDate < rule.validFrom ||
          currentDate > rule.validTo) {
        return {
          valid: false,
          reason: '规则未激活或已过期'
        };
      }

      // 检查每日限制
      if (rule.dailyLimit) {
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        const dailyCount = await PointTransaction.count({
          where: {
            ruleId,
            userId,
            createdAt: {
              [Op.gte]: today
            }
          }
        });

        if (dailyCount >= rule.dailyLimit) {
          return {
            valid: false,
            reason: '已达到每日限制'
          };
        }
      }

      // 检查每月限制
      if (rule.monthlyLimit) {
        const firstDayOfMonth = new Date();
        firstDayOfMonth.setDate(1);
        firstDayOfMonth.setHours(0, 0, 0, 0);
        const monthlyCount = await PointTransaction.count({
          where: {
            ruleId,
            userId,
            createdAt: {
              [Op.gte]: firstDayOfMonth
            }
          }
        });

        if (monthlyCount >= rule.monthlyLimit) {
          return {
            valid: false,
            reason: '已达到每月限制'
          };
        }
      }

      return {
        valid: true,
        points: rule.points
      };
    } catch (error) {
      logger.error(`验证积分规则 ${ruleId} 用户 ${userId} 时出错:`, error);
      throw error;
    }
  }

  /**
   * 获取积分规则使用统计
   * @param {number} ruleId - 积分规则ID
   * @param {Date} startDate - 开始日期
   * @param {Date} endDate - 结束日期
   * @returns {Promise<Object>} - 统计结果
   */
  async getRuleUsageStats(ruleId, startDate, endDate) {
    try {
      const where = {
        ruleId,
        createdAt: {}
      };

      if (startDate) {
        where.createdAt[Op.gte] = startDate;
      }
      if (endDate) {
        where.createdAt[Op.lte] = endDate;
      }

      const totalTransactions = await PointTransaction.count({ where });
      const totalPoints = await PointTransaction.sum('points', { where });
      const uniqueUsers = await PointTransaction.count({
        where,
        distinct: true,
        col: 'userId'
      });

      // Get daily usage
      const dailyUsage = await PointTransaction.findAll({
        where,
        attributes: [
          [PointTransaction.sequelize.fn('DATE', PointTransaction.sequelize.col('createdAt')), 'date'],
          [PointTransaction.sequelize.fn('COUNT', '*'), 'count'],
          [PointTransaction.sequelize.fn('SUM', PointTransaction.sequelize.col('points')), 'points']
        ],
        group: [PointTransaction.sequelize.fn('DATE', PointTransaction.sequelize.col('createdAt'))]
      });

      return {
        totalTransactions,
        totalPoints,
        uniqueUsers,
        dailyUsage
      };
    } catch (error) {
      logger.error(`Error getting usage stats for rule ${ruleId}:`, error);
      throw error;
    }
  }
}

module.exports = new PointRuleService(); 